from decorators import Transactional
from models.role_menu import RoleMenu
from models.menu import Menu
from models.user import User
from models.user_role import UserRole
from tools import generate_id
from tools.db_tool import DbTool


class RbacService:
    """
    RBAC模块业务处理类
    """

    def __init__(self, db=None):
        if db is not None:
            self.db = db
        else:
            from models import db

            self.db = db

    def get_in_cache(self, roleId, appCode):
        """
        从缓存中获取角色权限
        :param roleId
        :param appCode
        :return:
        """
        roleMenuList = (
            self.db.session.query(RoleMenu).filter(RoleMenu.roleId == roleId).all()
        )
        menu_ids = [role_menu.menuId for role_menu in roleMenuList]
        q = self.db.session.query(Menu)
        q.filter(Menu.appCode == appCode)
        if len(menu_ids) > 0:
            q = q.filter(Menu.id.in_(menu_ids))
        menuList = q.all()
        perms = [menu.code for menu in menuList]
        return perms

    def get_perm_in_cache(self, roleIds, appCode):
        """
        从缓存中获取角色权限
        :param roleIds
        :param appCode
        :return:
        """
        if len(roleIds) == 0:
            return []
        # 遍历roleIds,调用get_in_cache方法获取权限
        perms = []
        for roleId in roleIds:
            perms.extend(self.get_in_cache(roleId, appCode))
        return perms

    def role_menu_ids(self, roleId):
        """
        获取角色菜单ID列表
        """
        roleMenuList = (
            self.db.session.query(RoleMenu).filter(RoleMenu.roleId == roleId).all()
        )
        menu_ids = [str(role_menu.menuId) for role_menu in roleMenuList]
        return menu_ids

    @Transactional()
    def save_role_menu(self, roleMenus):
        """
        保存角色菜单
        """
        if roleMenus is None or len(roleMenus) == 0:
            return
        roleId = roleMenus[0].get("roleId")
        # 删除角色菜单
        self.db.session.query(RoleMenu).filter(RoleMenu.roleId == roleId).delete()
        for item in roleMenus:
            # model的default生成的id受缓存影响会主键冲突，所以这里要手动设置一下id
            item["id"] = generate_id()
            self.db.session.add(RoleMenu(**item))

    def user_list_by_role_id(self, roleId, keywords, pageNum, pageSize):
        """
        根据角色ID获取用户列表
        """
        userRoleList = (
            self.db.session.query(UserRole).filter(UserRole.roleId == roleId).all()
        )
        userIds = [str(user_role.userId) for user_role in userRoleList]
        if len(userIds) == 0:
            return []
        q = DbTool.filter_by_custom(User).filter(User.id.in_(userIds))
        q = q.filter(User.adminType != 1)
        if keywords is not None and len(keywords) > 0:
            q = q.filter(User.userName.like("%" + keywords + "%"))

        page = q.paginate(pageNum, pageSize, False)
        return User.to_page(page)

    @Transactional()
    def remove_user_role(self, userRoles):
        """
        删除用户角色
        """
        if userRoles is None or len(userRoles) == 0:
            return
        for item in userRoles:
            self.db.session.query(UserRole).filter(
                UserRole.userId == item.get("userId"),
                UserRole.roleId == item.get("roleId"),
            ).delete()

    def user_list_exclude_role_id(self, roleId, keywords, pageNum, pageSize):
        """
        获取用户列表-排除指定角色
        """
        userRoleList = (
            self.db.session.query(UserRole).filter(UserRole.roleId == roleId).all()
        )
        userIds = [str(user_role.userId) for user_role in userRoleList]
        q = DbTool.filter_by_custom(User)
        if len(userIds) != 0:
            q = q.filter(User.id.notin_(userIds))
        q = q.filter(User.adminType != 1)
        if keywords is not None and len(keywords) > 0:
            q = q.filter(User.userName.like("%" + keywords + "%"))
            q = q.filter(User.realName.like("%" + keywords + "%"))

        page = q.paginate(pageNum, pageSize, False)
        return User.to_page(page)

    @Transactional()
    def save_user_role(self, userRoles):
        """
        添加用户角色关系
        """
        if userRoles is None or len(userRoles) == 0:
            return
        for userRole in userRoles:
            roleId = userRole.get("roleId")
            userId = userRole.get("userId")
            count = (
                self.db.session.query(UserRole)
                .filter(UserRole.roleId == roleId)
                .filter(UserRole.userId == userId)
                .count()
            )
            if count > 0:
                continue
            self.db.session.add(UserRole(**userRole))
